#pragma once

#include "ArkGraphicBase.h"
#include "VFS/cpkgfile.h"
//namespace ArkGraphic
//{

class CResourceContainer;
class CResourceRecycle;

class CResUnit
{
	CResourceRecycle*	m_pRecycle;
	CResourceContainer* m_pContainer;
	uint32				m_uSize;

protected:
	string				m_szName;

public:
	CResUnit( CResourceContainer* pContainer, CResourceRecycle* pRecycle, const string& szName );
	virtual ~CResUnit();
	virtual UINT AddRef() = 0;
	void	FreeRes();
	void	CreateResFile( CPkgFile& ResFile, bool bShowMsg = true );
	void	SetBufSize( uint32 uSize );
	void	AddBufSize( uint32 uSize );
	uint32	GetBufSize(){ return m_uSize; };
	void	Reclaim();

	CResourceContainer* Container()	{ return m_pContainer; }
	CResourceRecycle* Recycle()		{ return m_pRecycle;   }
};

class CResourceContainer
{
	string Strlwr( const string& str )
	{
		string NewStr = str;
		for( int i = 0; i < (int)NewStr.length(); i++ )
			if( NewStr[i] >= 'A' && NewStr[i] <= 'Z' )
				NewStr[i] = NewStr[i] - 'A' + 'a';
		return NewStr;
	}

protected:
	map< string, CResUnit* > m_ResContainer;

public:
	~CResourceContainer()
	{
		//map< string, void* >::iterator Res = m_ResContainer.begin();
		//for( ; Res != m_ResContainer.end(); Res++ )
		//	OutputDebugString( ( Res->first + "\n" ).c_str() );
	}

	CResUnit* GetResFromContainer( const string& Name )
	{
		map< string, CResUnit* >::iterator Res = m_ResContainer.find( Strlwr( Name ) );
		if( Res == m_ResContainer.end() )
			return NULL;

		return Res->second;
	}

	void AddResToContainer( const string& Name, CResUnit* Res )
	{
		m_ResContainer[ Strlwr( Name ) ] = Res;
	}

	void Erase( const string& Name )
	{
		m_ResContainer.erase( Strlwr( Name ) );
	}
};

class CResourceRecycle : public CResourceContainer
{
	uint32	m_uCurBufSize;
	uint32	m_uMaxBufSize;
public:
	CResourceRecycle( uint32 uBufSize ) : m_uMaxBufSize( uBufSize ), m_uCurBufSize(0) {}
	uint32 MaxBufSize(){ return m_uMaxBufSize; }
	uint32 CurBufSize(){ return m_uCurBufSize; }

	void Clear()
	{
		for( map< string, CResUnit* >::iterator it = m_ResContainer.begin(); it != m_ResContainer.end(); )
		{
			delete (it++)->second;
		}
	}

	void AddSize( uint32 nSize )
	{
		map< string, CResUnit* >::iterator it = m_ResContainer.begin();
		for( ; it != m_ResContainer.end() && m_uCurBufSize + nSize > m_uMaxBufSize; )
		{
			m_uCurBufSize -= it->second->GetBufSize();
			delete (it++)->second;
		}
		m_uCurBufSize += nSize;
	}
};

class CResMgr
{
	CResourceContainer		m_VideoMemContainer;
	CResourceRecycle		m_VideoMemRecycle;
	CResourceContainer		m_SystemMemContainer;
	CResourceRecycle		m_SystemMemRecycle;
public:
	CResMgr();

	CResUnit* FindResInVedioMem( const string& szName )
	{
		CResUnit* pRes = m_VideoMemContainer.GetResFromContainer( szName );
		if( !pRes )
			pRes = m_VideoMemRecycle.GetResFromContainer( szName );
		return pRes;
	}

	CResUnit* FindResInSystemMem( const string& szName )
	{
		CResUnit* pRes = m_SystemMemContainer.GetResFromContainer( szName );
		if( !pRes )
			pRes = m_SystemMemRecycle.GetResFromContainer( szName );
		return pRes;
	}

	void Clear()
	{
		m_VideoMemRecycle.Clear();
		m_SystemMemRecycle.Clear();
	}

	CResourceContainer* VideoMemContainer()
	{
		return &m_VideoMemContainer;
	}

	CResourceRecycle* VideoMemRecycle()
	{
		return &m_VideoMemRecycle;
	}

	CResourceContainer* SystemMemContainer()
	{
		return &m_SystemMemContainer;
	}

	CResourceRecycle* SystemMemRecycle()
	{
		return &m_SystemMemRecycle;
	}
};

// }
